#!/bin/bash
# by wangyuan
#v0.4 更改分发机制
#v0.5 使用for循环
#v0.6 增加子脚本执行的判断，增加分发前的判断
#v0.7 增加两个参数 第三个参数为运行内存（1G,2G,...,8G），第四个参数为启动节点数(n1,n2,n3,..,n8)

#v2.00 隐藏部分日志显示，全部日志写入日志文件中.
#v2.00 添加更改CMDB状态, 1,为发布成功; 2, 为发布中; 3, 为发布失败


ctx="/opt/app/spring/temp"
bakdir="/opt/app/spring/backup"
baseDir="/opt/app/spring"
LocalDir="/opt/app"
VersionServerIP=10.201.32.109
VersionType=spring
ReleaseDate="`date '+%Y%m%d'`_`date '+%H%M%S'`"
BakDate="`date '+%Y%m%d'`-`date '+%H%M%S'`"
ScriptKeepPeriod=1
VerSion=1.00

logfile=/opt/logs/spring/${ReleaseDate}_${2}_spring_fabu.log
touch $logfile >> /dev/null
if [ $? -ne 0 ];then
    logfile=/home/netty/${ReleaseDate}_${2}_spring_fabu.log
fi


function Setlog()
{
    echo $1 >> $logfile
}

echo 当前时间为：$ReleaseDate
Setlog "当前时间为：$ReleaseDate"
echo 备份目录是：$bakdir/${1}/$ReleaseDate
Setlog "备份目录是：$bakdir/${1}/$ReleaseDate"
echo 参数1是：${1}
echo 参数2是：${2}
echo 参数3是：${3}
echo 参数4是：${4}
echo 当前临时目录是：${ctx}
echo ""

Setlog "参数1是：${1}"
Setlog "参数2是：${2}"
Setlog "参数3是：${3}"
Setlog "参数4是：${4}"
Setlog "当前临时目录是：${ctx}"

function GetIP()
{
LocalIP=`/sbin/ifconfig |grep "inet addr" |awk '{print $2}' |awk -F : '{print $2}' | grep -v '127.0.0.1'`
echo "======================>【0.发布初始化检测】<========================="
Setlog "======================>【0.发布初始化检测】<========================="
echo "---->本机IP为：$LocalIP"
Setlog "---->本机IP为：$LocalIP"
}

function UpdateScripts()
{
Setlog "---->开始备份当前脚本[$1.sh]"
Setlog "    |--->备份到$LocalDir/$VersionType/backup/script/$BakDate"
if [ ! -d "$LocalDir/$VersionType/backup/script/$BakDate" ]; then 
  mkdir -p $LocalDir/$VersionType/backup/script/$BakDate
fi 
mv $LocalDir/$VersionType/$1.sh $LocalDir/$VersionType/backup/script/$BakDate
Setlog "    |--->清理$ScriptKeepPeriod天前的脚本备份文件"
rm -rf `find $LocalDir/$VersionType/backup/script -maxdepth 2 -mindepth 1 -mtime +$ScriptKeepPeriod | grep sh`
Setlog "---->开始下载最新脚本[$1.sh]"
cd $LocalDir/$VersionType/
wget -q http://$VersionServerIP/$VersionType/sit/$VersionServer/$1.sh
if [ $? != 0 ]
then 
        echo "    |--->[×]更新失败，进行[$1.sh]脚本回滚"
        Setlog "    |--->[×]更新失败，进行[$1.sh]脚本回滚"
        cp  $LocalDir/$VersionType/backup/script/$BakDate/$1.sh $LocalDir/$VersionType
        chmod 755 $LocalDir/$VersionType/$1.sh
else
        Setlog "    |--->[√]更新[$1.sh]成功"
        chmod 755 $LocalDir/$VersionType/$1.sh
        VersionClient=`grep "^VerSion=" $LocalDir/$VersionType/$1.sh  | cut -d = -f 2`
        Setlog "    |--->当前脚本版本号为:$VersionClient"
fi
}

function VersionCheck()
{
VersionClient=`grep "^VerSion=" $LocalDir/$VersionType/$1.sh  | cut -d = -f 2`
if [ $? = 0  ]
then 
	Setlog "    |--->[√]获取本地脚本的版本号成功，判断版本号合法性"
	LengthV=`echo $VersionClient | wc -L`
    if [ $LengthV -lt 4 ]; then
		echo "        |--->[×]版本号长度异常,开始强制更新"
		Setlog "        |--->[×]版本号长度异常,开始强制更新"
		UpdateScripts $1
	else
		if [[ $VersionClient =~ ^[0-9]*.?[0-9]*$ ]] 
			then 
			Setlog "        |--->[√]版本号格式正确"
			VersionClient1=`echo $VersionClient | sed "s \.  "`
			VersionServer1=`echo $VersionServer | sed "s \.  "`
			if [ $VersionClient1 -eq $VersionServer1  ]
				then 
					echo "    |--->[√]当前脚本$1为新版！均为$VersionClient"
					Setlog "    |--->[√]当前脚本$1为最新版！均为$VersionClient"
			elif
				 [ $VersionClient1 -lt $VersionServer1  ]
				then
				ccc=`expr $VersionServer1 - $VersionClient1`
				
				if [ $ccc -gt 1 -a $ccc -lt 10 ] 
					then 
					echo "    |--->服务器版本为:$VersionServer"
					Setlog "    |--->服务器版本为:$VersionServer"
					echo "    |--->本地版本为:$VersionClient"
					Setlog "    |--->本地版本为:$VersionClient"
					echo "    |--->[!]$1版本在兼容范围内,可用。但建议更新！"
					Setlog "    |--->[!]$1版本在兼容范围内,可用。但建议更新！"
				else 
					echo "    |--->服务器版本为:$VersionServer"
					Setlog "    |--->服务器版本为:$VersionServer"
					echo "    |--->本地版本为:$VersionClient"
					Setlog "    |--->本地版本为:$VersionClient"
					echo "    |--->[×]当前$1版本和服务器版本差距太大，开始更新。。。。。"
					Setlog "    |--->[×]当前$1版本和服务器版本差距太大，开始更新。。。。。"
					UpdateScripts $1	 
				fi
			else

				 echo "    |--->[×]当前版本比服务器还新！怎么可能！！！！"
				 Setlog "    |--->[×]当前版本比服务器还新！怎么可能！！！！"
				 UpdateScripts $1	 
			fi			
		else
			echo "    |--->[×]版本号格式异常，开始强制更新"
			Setlog "    |--->[×]版本号格式异常，开始强制更新"
			UpdateScripts $1
		fi
    fi
else
	echo "    |--->[×]获取本地脚本版本号失败，开始强制更新。。"
	Setlog "    |--->[×]获取本地脚本版本号失败，开始强制更新。。"
	UpdateScripts $1
fi

}


function CheckServer()
{
#echo "=========================================================================="
Setlog "---->开始检测$1版本...."
VersionServer=`/usr/bin/curl -s -m 2 http://$VersionServerIP/$VersionType/version/sit/$1.version`
if [ $? = 0 ]
    then
                echo  $VersionServer | grep nginx > /dev/null
                        if [ $? != 0 ] 
                                then 
                                VersionCheck $1
                        else
                                echo "    |--->[×]服务器上无[$1.sh]版本号,请检测服务器配置"
                                Setlog "    |--->[×]服务器上无[$1.sh]版本号,请检测服务器配置"
                                echo "    |--->[!]跳过版本校验，继续发布...."
                                Setlog "    |--->[!]跳过版本校验，继续发布...."
                        fi

else
                echo "    |--->[×]版本服务器无响应,请检测服务器配置"
                Setlog "    |--->[×]版本服务器无响应,请检测服务器配置"
                echo "    |--->[!]跳过版本校验，继续发布...."
                Setlog "    |--->[!]跳过版本校验，继续发布...."
fi
}

function FilesExist()
{
if 
        $(ls -l  $baseDir/temp/$1 | grep jar > /dev/null) 
then 
        Setlog "    |--->[√]jar包推送成功,准备发布工程..."
else 
        echo "    |--->[×]获取jar包失败！！！本次发布被取消！无需回滚"
        Setlog "    |--->[×]获取jar包失败！！！本次发布被取消！无需回滚"
        exit 1
fi
}



function  distribute()
{

for((i=1;i<=$3;i++))        
    do 
		Setlog "    |--->[√]正在操作${2}$i"
        Setlog "        |--->[√]删除${ctx}/${1}$i中旧的jar包和lib库"
        rm -rf ${ctx}/${1}$i
        Setlog "        |--->[√]正在分发新jar包及lib库到${ctx}/${1}$i"
        cp -r ${ctx}/${1} ${ctx}/${1}$i
		sleep 1
    done

}

function ReleaseProject()
{
#---------修改如果节点数为1时,所执行的启动命令---------->
if [ $6 -eq 1 ];then
    Setlog "此服务器启动${4}个节点"

    echo "======================>【1.开始发布${2}工程】<========================="
    /opt/app/spring/start.sh ${1} ${2} ${3} ${4} ${5} $logfile
    result=$?
    Setlog "启动结果$result"
    if [ $result -ne 0 ];then
        exit 1
    fi
fi
#------------------------------------------------------->

#---------修改如果节点数大于1时，所执行的启动命令------->
if [ $6 -gt 1 ];then
for((i=1;i<=$6;i++))
        do
		Setlog "---------------------------------------"
                echo "======================>【1.开始发布${2}$i工程】<========================="
                Setlog "======================>【1.开始发布${2}$i工程】<========================="
		Setlog "---------------------------------------"
		Setlog "---->检测文件分发情况"
		FilesExist ${1}$i ${2}$i
		/opt/app/spring/start.sh ${1}$i ${2}$i ${3} ${4} ${5} $logfile
		result=$?
		if [ $result -ne 0 ]
			then 
				echo "${2}$i 节点启动失败,请检查"
				exit 1

		fi
    done
fi

}

function MonitorProject()
{
#----------节点数为1时,检测命令如下------------------------->
if [ $3 -eq 1 ];then
    /opt/app/spring/apimonitor.sh $1 $2 $logfile
fi
#----------------------------------------------------------->

if [ $3 -gt 1 ];then
    for((i=1;i<=$3;i++))
        do /opt/app/spring/apimonitor.sh ${1}$i ${2}$i $logfile
    done

    fi
}

function DeleteSourceDir()
{
Setlog "--------->3.删除分发源目录<---------------------------"
Setlog ${ctx}/${1}
rm -rf ${ctx}/${1}
}


function CheckPromotion()
{
#应文明任务调度脚本段
echo "---->正在调用http://$LocalIP:7210/promotion/job，by应文明"
Setlog "---->正在调用http://$LocalIP:7210/promotion/job，by应文明"
echo "    |--->"
Setlog "    |--->"
/usr/bin/curl  -H "Content-Type: application/json" -X POST -d '{"coupon_template_id":710,"pageSize":10,"pageNum":1}'  http://$LocalIP:7210/promotion/job/test.htm
echo ""
}




#-----------------添加的内容---------------------------------------------------------------------------------------------------------------->

#########################################################################################################

    #monitor="n`grep $2 $LocalDir/appPorts.properties | wc -l`" #没有指定，以配置文件为准！
    #echo "     |--->[W]检测到参数为默认参数4GB内存，根据配置内容来启动节点数$monitor"

#########################################################################################################
#
#
#
#
# 脚本开始
function usag_help(){
echo "脚本帮助信息"
echo "脚本运行格式如下"
echo "shard-spring.sh dirpath/project_path project_path -Xmsng -Xmxmg [pre|prd|sit|prod] num_monitor [y]"
echo "参数说明:"
echo "    dirpath/project_path --->例如： phone/phone-business"
echo "    project_path ---> 例如：phone-business"
echo "    -Xmsng 是jvm的-Xms参数 n是指定的最小内存数,g为单位[m,g]"
echo "    -Xmxmg 是jvm的-Xmx参数 m是指定的最大内存数,g为单位[m,g]"
echo "    **不要忘记短线-  -_-!!"
echo ""
echo "    [prd|pre|sit|prod] 启动参数指定其中一个,或你认为正确的参数!!!"
echo "    num_monitor 是启动节点数:n4/N3"
echo "    y:是否为应文明任务调度"
echo "=================================================="
echo "如果为如下运行格式:"
echo "    shard-spring.sh dirpath/project_path project_path"
echo "    物理机内存默认为:-Xms6g -Xmx6g"
echo "    虚拟机内存默认为:-Xms6g -Xmx6g"
echo "=================================================="
echo ""
echo "----------------------------------------"
echo "|此脚本暂时支持3，6，7 个参数！！！！"
echo "|如果多于两个传参请上全部参数！！！！  |"
echo "----------------------------------------"
echo ""

}

# 判断是否为虚拟机
function ifvm(){
ls /bin/dmesg >> /dev/null
if [ $? -eq 0 ];then
    /bin/dmesg | grep -E "VMware|virtio-pci" >> /dev/null
    if [ $? -eq 0 ];then
        echo "此服务器为虚拟机"
    else
        echo "此服务器为物理机"
    fi
else
    echo "/bin/dmesg 命令不存在,无法判断是否为虚拟机,请注意!!!"
fi
    
}
# 判断传递参数个数

if [ $# -eq 3 ];then #当两个参数，也就是没有指定jvm内存和启动节点数时
    ls /bin/dmesg >> /dev/null
    if [ $? -ne 0 ];then
        echo "/bin/dmesg 命令不存在,无法检测服务器是否为虚拟机,此时采用默认的参数: -Xms6g -Xmx6g"
        echo "如果已知请传递相应的参数。"
        echo "虚拟机默认jvm参数为：-Xms6g -Xmx6g"
        echo "物理机默认jvm参数为：-Xms6g -Xmx6g"
        echo ""

        jvm1="-Xms6g"
        jvm2="-Xmx6g"

    else
        /bin/dmesg | grep -E "VMware|virtio-pci" >> /dev/null
        if [ $? -eq 0 ];then
            echo "此服务器为虚拟机"
            jvm1="-Xms6g"
            jvm2="-Xmx6g"
        else
            echo "此服务器为物理机"
            jvm1="-Xms6g"
            jvm2="-Xmx6g"
        fi
    fi
    monitor=n`grep $2 $LocalDir/appPorts.properties | grep -v "^#" | wc -l`
    ENV=$3

elif [ $# -eq 6 ];then
    ifvm
    jvm1=$3
    jvm2=$4
    ENV=$5
    monitor=$6
    echo $jvm1 | grep "\-Xms" >> /dev/null
    if [ $? -ne 0 ];then
        echo "jvm $jvm1 参数错误,请修改后再运行！！"
        usag_help
        exit 3
    fi
    echo $jvm2 | grep "\-Xmx" >> /dev/null
    if [ $? -ne 0 ];then
        echo "jvm $jvm2 参数错误,请修改后再运行！！"
        usag_help
        exit 4
    fi 
elif [ $# -eq 7 ];then
    ifvm
    jvm1=$3
    jvm2=$4
    monitor=$5
    promotionstatus=$6
    echo "$jvm1" | grep "\-Xms" >> /dev/null
    if [ $? -ne 0 ];then
        echo "$jvm1 参数错误,请检查!!!"
        usag_help
        exit 55
    fi
    echo "$jvm2" | grep "\-Xmx" >> /dev/null
    if [ $? -ne 0 ];then
        echo "$jvm2 参数错误,请检查!!!"
        usag_help
        exit 54
    fi
    
    
else
    echo "参数错误！！！"
    Setlog "参数错误！！！"
    ifvm
    echo "---------------------------------"
    echo "---------------------------------"
    usag_help
    exit 5
fi


#判断节点参数
case $monitor in
        n1|N1|n2|N2|n3|N3|n4|N4|n5|N5|n6|N6|n7|N7|n8|N8)
    monitor_num=`echo $monitor | sed "s/[a-zA-Z]//g"`
    conf_num=`grep $2 $LocalDir/appPorts.properties | grep -v "^#" | wc -l`
    if [ $monitor_num -eq $conf_num ];then
        echo "在此服务器上启动的$2项目节点为: $monitor_num"
        Setlog "在此服务器上启动的$2项目节点为: $monitor_num"
    else
        echo "传参节点数$monitor_num 与配置文件中相应的节点数$conf_num不相符，请检查后再试!!!"
        usag_help
        exit 5
    fi
    ;;
        *)
    echo "节点参数错误"
    Setlog "节点参数错误"
    usag_help
    exit 4
esac


case "$promotionstatus" in
        y|Y|Yes|YES|yes|yES|yEs|YeS|yeS)
    promotionstatus="y"
    ;;
        n|N|No|NO|no|nO)
    promotionstatus="n"
    ;;
        *)
    promotionstatus="n"
esac

#--------------------------------------------------------------------------------------------------------------------------------------->

GetIP
CheckServer shard-spring
sleep 2
CheckServer start
sleep 2
CheckServer apimonitor
sleep 2
CheckServer springstart
sleep 2

echo ""

#------添加的内容----------------------------------------->
#修改脚本权限
chmod 755 $LocalDir/$VersionType/start.sh
chmod 755 $LocalDir/$VersionType/apimonitor.sh
chmod 755 $LocalDir/$VersionType/shard-spring.sh
chmod 755 $LocalDir/$VersionType/springstart.sh
#--------------------------------------------------------->

Setlog "---->检测源文件推送情况"
FilesExist $1 $2
sleep 1

Setlog "---->开始分发新的包到临时目录"

#--------修改的内容:添加节点参数---------------------------------------------------------->
if [ $monitor_num -gt 1 ];then
    distribute $1 $2 $monitor_num
fi
#----------------------------------------------------------------------------------------->

sleep 1
#echo "======================>【1.开始发布${2}工程】<========================="
#Setlog "======================>【1.开始发布${2}工程】<========================="
#--------修改的内容:添加内存参数和节点参数---------------------------------------------------------->
ReleaseProject $1 $2 $jvm1 $jvm2 $ENV $monitor_num
#--------------------------------------------------------------------------------------------------->
sleep 1
if [ $promotionstatus = y ]
then
        CheckPromotion
fi

#--------修改的内容:添加节点参数---------------------------------------------------------->
MonitorProject $1 $2 $monitor_num
#----------------------------------------------------------------------------------------->
DeleteSourceDir $1 $2

echo ""
echo "==================================Log File Info===================================="
echo "更多详细日志请查看本机 [ $logfile ] ||" 
echo "==================================================================================="
echo ""
